package com.njcb.ams.repository.dao.base.intercept;

import com.njcb.ams.factory.comm.DataBus;
import com.njcb.ams.repository.dao.SysAlterRecordDAO;
import com.njcb.ams.portal.SysBaseDefine;
import com.njcb.ams.support.annotation.OperRecord;
import com.njcb.ams.support.comm.SequenceService;
import com.njcb.ams.util.AmsBeanUtils;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.springframework.core.annotation.AnnotationUtils;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.Properties;

/**
 * 根据注解自动记录操作记录
 * @author liuyanlong
 *
 */
@Intercepts({ @Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }) })
public class OpeInfoInterceptor implements Interceptor {

	/**
	 * 修改人
	 */
	public static final String CONDUCT_USER 		= "conductUser";

	/**
	 * 修改时间
	 */
	public static final String CONDUCT_TIME 		= "conductTime";

	/**
	 * 数据期数
	 */
	public static final String PERIODS 		= "periods";



	/**
	 * @see Interceptor#intercept(Invocation)
	 * @param invocation 调用
	 * @return 调用
	 * @throws Throwable 调用异常
	 */
	@Override
	public Object intercept(Invocation invocation) throws Throwable {
		Object[] args = invocation.getArgs();
		SqlCommandType sqlCommandType = SqlCommandType.SELECT;
		for (int i = 0; i < args.length; i++) {
			Object arg = args[i];
			if (arg instanceof MappedStatement) {
				MappedStatement ms = (MappedStatement) arg;
				sqlCommandType = ms.getSqlCommandType();
				if (sqlCommandType == SqlCommandType.INSERT) {
					continue;
				} else if (sqlCommandType == SqlCommandType.UPDATE) {
					continue;
				} else if (sqlCommandType == SqlCommandType.DELETE) {
					continue;
				} else {
					break;
				}
			}
			if (arg instanceof Map) {
				Map<?, ?> map = (Map<?, ?>) arg;
				for (Object obj : map.values()) {
					setProperty(obj);
				}
			} else {
				if (null != arg) {
					setProperty(arg);
					if (sqlCommandType == SqlCommandType.INSERT || sqlCommandType == SqlCommandType.UPDATE || sqlCommandType == SqlCommandType.DELETE) {
						saveAlterRecord(arg);
					}
				}
			}
		}

		return invocation.proceed();
	}

	/**
	 * @param arg
	 */
	private void saveAlterRecord(Object arg) {
		if (AnnotationUtils.isAnnotationDeclaredLocally(OperRecord.class, arg.getClass())) {
			if (DataBus.isNotNull() && DataBus.getUserAttr() == SysBaseDefine.USER_ATTR_REAL) {
				SysAlterRecordDAO.getInstance().saveRecord(arg);
			}
		}

	}

	/**
	 * @param obj
	 * @throws @throws
	 *             Exception
	 */
	private void setProperty(Object obj) throws Exception {
		if (null == obj) {
			return;
		}
		// 数据修改人
		if (AmsBeanUtils.isContainAndEmptyField(obj, CONDUCT_USER)) {
			AmsBeanUtils.setProperty(obj, CONDUCT_USER, null == DataBus.getUncheckInstance() ? "" : DataBus.getUserId());
		}
		// 数据修改时间
		if (AmsBeanUtils.isContainAndEmptyField(obj, CONDUCT_TIME)) {
			AmsBeanUtils.setProperty(obj, CONDUCT_TIME, LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
		}
		// 数据期数
		if (AmsBeanUtils.isContainAndEmptyField(obj, PERIODS)) {
			AmsBeanUtils.setProperty(obj, PERIODS, SequenceService.getInstance().genSeqStr(SysBaseDefine.SEQ_VALUENO_PERIODS));
		}
	}

	@Override
	public Object plugin(Object target) {
		return Plugin.wrap(target, this);
	}

	/**
	 * @see Interceptor#setProperties(Properties)
	 * @param properties
	 */
	@Override
	public void setProperties(Properties properties) {
	}

}
